#include "user_sid31_service.h"

#include "uds_service.h"
#include "user_uds.h"

int16_t uds_erase_start_routine(uint8_t *rec_buf, uint8_t *rsp_buf)
{

    int16_t                              ret;
    uint32_t                             flash_erase_sector_num;
    routine_ctrl_req_struct             *routine_ctrl_req;
    routine_ctrl_positive_resp_struct   *routine_ctrl_pstv_resp;
    routine_ctrl_record_erase_mem_struct routine_ctrl_record_erase_mem;

    routine_ctrl_req = (routine_ctrl_req_struct *)rec_buf;

    routine_ctrl_pstv_resp = (routine_ctrl_positive_resp_struct *)rsp_buf;

    memcpy((uint8_t *)(&routine_ctrl_record_erase_mem), routine_ctrl_req->routine_ctrl_record_data, 9);

    endian_shift((uint8_t *)(&routine_ctrl_record_erase_mem.mem_start_add), 4);

    endian_shift((uint8_t *)(&routine_ctrl_record_erase_mem.mem_size), 4);

    // 检查起始地址、内存大小的字节长度
    if (routine_ctrl_record_erase_mem.mem_add_and_size_byte_len != 0x44) {

        ret = -NRC_REQUEST_OUT_OF_RANGE;

        return ret;
    }

    // 检查内存起始地址
    if (routine_ctrl_record_erase_mem.mem_start_add != UDS_APP_UPDATA_START_ADDR) {

        ret = -NRC_REQUEST_OUT_OF_RANGE;

        return ret;
    }

    // 检查内存大小
    if (routine_ctrl_record_erase_mem.mem_size >= (FLASH_ADDR_APP_CODE_MAX - FLASH_ADDR_APP_CODE)) {

        ret = -NRC_REQUEST_OUT_OF_RANGE;

        return ret;
    }

    // 计算擦除扇区总数
    flash_erase_sector_num = routine_ctrl_record_erase_mem.mem_size / FLASH_ERASE_UNIT_BYTE;

    // 对齐扇区
    if (((routine_ctrl_record_erase_mem.mem_size) % FLASH_ERASE_UNIT_BYTE) != 0) {

        flash_erase_sector_num++;
    }

    // 这里不读取下发的起始地址，用户有自己的flash区规划
    // board_status.board_uds_status.uds_sid31_service.flash_erase_addr =
    // routine_ctrl_record_erase_mem.mem_start_add;
    uds_status.uds_sid31_service.flash_erase_addr = FLASH_ADDR_APP_CODE;

    // 这里的大小已经扇区对齐了
    uds_status.uds_sid31_service.flash_erase_size = flash_erase_sector_num * FLASH_ERASE_UNIT_BYTE;

    // 准备应答数据
    routine_ctrl_pstv_resp->positive_resp_id = USD_GET_POSITIVE_RSP(routine_ctrl_req->sid);

    routine_ctrl_pstv_resp->subfunction = routine_ctrl_req->subfunction;

    routine_ctrl_pstv_resp->rid = routine_ctrl_req->rid;

    endian_shift((uint8_t *)(&routine_ctrl_pstv_resp->rid), 2);

    routine_ctrl_pstv_resp->routine_result_record_data[0] = (uint8_t)MAST_WAIT_ERASE_TIME;

    routine_ctrl_pstv_resp->routine_result_record_data[1] = (uint8_t)((uint16_t)MAST_WAIT_ERASE_TIME >> 8);

    endian_shift(routine_ctrl_pstv_resp->routine_result_record_data, 2);

    // 擦除服务标记
    uds_status.uds_sid31_service.erase_mem_routine_start_flag = 1;

    // 延时擦除,保证响应发送(擦写flash会关闭中断)
    uds_status.uds_sid31_service.erase_start_timeout = FUNC_DELAY_TIME;

    // 清擦除完成标志
    uds_status.uds_sid31_service.erase_finish_flag = 0;

    ret = ROUTINE_CTRL_POSTV_RESP_START_MESSAGE_LEN;

    return ret;
}

int16_t uds_req_erase_routine_result(uint8_t *rec_buf, uint8_t *rsp_buf)
{

    int16_t                            ret;
    routine_ctrl_req_struct           *routine_ctrl_req;
    routine_ctrl_positive_resp_struct *routine_ctrl_pstv_resp;

    // 检查是否执行过擦除服务
    if (uds_status.uds_sid31_service.erase_mem_routine_start_flag == 0) {

        ret = -NRC_REQUEST_SEQUENCE_ERROR;

        return ret;
    }

    uds_status.uds_sid31_service.erase_mem_routine_start_flag = 0;

    // 检查是否擦除完成
    if (uds_status.uds_sid31_service.erase_finish_flag == 0) {

        ret = -NRC_GENERAL_PROGRAMMING_FAILURE;

        return ret;
    }

    uds_status.uds_sid31_service.erase_finish_flag = 0;

    // 准备应答数据
    routine_ctrl_req = (routine_ctrl_req_struct *)rec_buf;

    routine_ctrl_pstv_resp = (routine_ctrl_positive_resp_struct *)rsp_buf;

    routine_ctrl_pstv_resp->positive_resp_id = (0x40 | routine_ctrl_req->sid);

    routine_ctrl_pstv_resp->subfunction = routine_ctrl_req->subfunction;

    routine_ctrl_pstv_resp->rid = routine_ctrl_req->rid;

    ret = ROUTINE_CTRL_RESP_ERASE_MEM_RESULT_LEN;

    return ret;
}

int16_t uds_check_mem_start_routine(uint8_t *rec_buf, uint8_t *rsp_buf)
{

    int16_t                               ret;
    routine_ctrl_record_check_mem_struct *routine_ctrl_record_check_mem;
    routine_ctrl_positive_resp_struct    *routine_ctrl_pstv_resp;

    routine_ctrl_record_check_mem = (routine_ctrl_record_check_mem_struct *)rec_buf;

    routine_ctrl_pstv_resp = (routine_ctrl_positive_resp_struct *)rsp_buf;

    // 存储收到的crc
    uds_status.uds_sid31_service.receive_crc32 = routine_ctrl_record_check_mem->check_value;

    endian_shift((uint8_t *)(&uds_status.uds_sid31_service.receive_crc32), 4);

#if 0

    //准备响应数据
    routine_ctrl_pstv_resp->positive_resp_id = USD_GET_POSITIVE_RSP(routine_ctrl_record_check_mem->sid);

	routine_ctrl_pstv_resp->subfunction = routine_ctrl_record_check_mem->subfunction;

	routine_ctrl_pstv_resp->rid = routine_ctrl_record_check_mem->rid;

    endian_shift((uint8_t* )(&routine_ctrl_pstv_resp->rid), 2);

    routine_ctrl_pstv_resp->routine_result_record_data[0] = (uint8_t)MAST_WAIT_ERASE_TIME;

	routine_ctrl_pstv_resp->routine_result_record_data[1] = (uint8_t)((uint16_t)MAST_WAIT_ERASE_TIME >> 8);

    endian_shift(routine_ctrl_pstv_resp->routine_result_record_data, 2);

    uds_status.uds_sid31_service.check_mem_routine_start_flag = 1;

    uds_status.uds_sid31_service.check_mem_start_timeout = 20;

#else // 这里直接检查crc，主机无需请求检查内存结果

    // TODO: 这里需要重新计算整片APP2区域的CRC
    if (uds_status.uds_sid31_service.receive_crc32 != uds_status.uds_sid36_service.total_crc) {

        // uds_status.uds_sid31_service.check_mem_finish_flag = 1;
        // USER_UDS_LOG("crc err:%x,%x\n", uds_status.uds_sid31_service.receive_crc32,
        //              uds_status.uds_sid36_service.total_crc);

        ret = -NRC_GENERAL_PROGRAMMING_FAILURE;

        return ret;
    }

    // 擦除需要写入数据标识符区域(boot最后2kByte空间)
    if (user_flash_n_page_erase(APP_UPDATA_NEED_FLAG_ADDR, 2) == 0) {

        USER_UDS_LOG("erase app updata need flag addr err\n");

        ret = -NRC_GENERAL_PROGRAMMING_FAILURE;

        return ret;
    }

    // 更新升级标志
    uds_status.uds_sid11_service.app_updata_flag = APP_UPDATA_CFG_WORD;

    if (user_flash_n_word_write(APP_UPDATA_NEED_FLAG_ADDR, &uds_status.uds_sid11_service.app_updata_flag,
                                1) == 0) {

        USER_UDS_LOG("write app updata need flag err\n");

        ret = -NRC_GENERAL_PROGRAMMING_FAILURE;

        return ret;
    }

    uds_status.uds_sid34_service.flash_program_crc = uds_status.uds_sid36_service.total_crc;

    // 写入编程起始地址和文件大小和文件crc32结果
    if (user_flash_n_word_write(APP_UPDATA_CHECK_DATA_ADDR,
                                &uds_status.uds_sid34_service.flash_program_addr, 3) == 0) {

        USER_UDS_LOG("write app updata check data err\n");

        ret = -NRC_GENERAL_PROGRAMMING_FAILURE;

        return ret;
    }

    // 准备响应数据
    routine_ctrl_pstv_resp->positive_resp_id = USD_GET_POSITIVE_RSP(routine_ctrl_record_check_mem->sid);

    routine_ctrl_pstv_resp->subfunction = routine_ctrl_record_check_mem->subfunction;

    routine_ctrl_pstv_resp->rid = routine_ctrl_record_check_mem->rid;

    endian_shift((uint8_t *)(&routine_ctrl_pstv_resp->rid), 2);

    routine_ctrl_pstv_resp->routine_result_record_data[0] = (uint8_t)MAST_WAIT_ERASE_TIME;

    routine_ctrl_pstv_resp->routine_result_record_data[1] = (uint8_t)((uint16_t)MAST_WAIT_ERASE_TIME >> 8);

    endian_shift(routine_ctrl_pstv_resp->routine_result_record_data, 2);

#endif

    ret = ROUTINE_CTRL_POSTV_RESP_START_MESSAGE_LEN;

    return ret;
}

int16_t uds_req_check_mem_routine_result(uint8_t *rec_buf, uint8_t *rsp_buf)
{

    int16_t                            ret;
    routine_ctrl_req_struct           *routine_ctrl_req;
    routine_ctrl_positive_resp_struct *routine_ctrl_pstv_resp;

    routine_ctrl_req = (routine_ctrl_req_struct *)rec_buf;

    routine_ctrl_pstv_resp = (routine_ctrl_positive_resp_struct *)rsp_buf;

    // 检查是否执行开始检查内存
    if (uds_status.uds_sid31_service.check_mem_routine_start_flag == 0) {

        ret = -NRC_REQUEST_SEQUENCE_ERROR;

        return ret;
    }

    uds_status.uds_sid31_service.check_mem_routine_start_flag = 0;

    if (uds_status.uds_sid31_service.check_mem_finish_flag == 0) {

        ret = -NRC_GENERAL_PROGRAMMING_FAILURE;

        return ret;
    }

    uds_status.uds_sid31_service.check_mem_finish_flag = 0;

    // 擦除需要写入数据标识符区域(boot最后2kByte空间)
    if (user_flash_n_page_erase(APP_UPDATA_NEED_FLAG_ADDR, 2) == 0) {

        ret = -NRC_GENERAL_PROGRAMMING_FAILURE;

        return ret;
    }

    // 更新升级标志
    uds_status.uds_sid11_service.app_updata_flag = APP_UPDATA_CFG_WORD;

    if (user_flash_n_word_write(APP_UPDATA_NEED_FLAG_ADDR, &uds_status.uds_sid11_service.app_updata_flag,
                                1) == 0) {

        ret = -NRC_GENERAL_PROGRAMMING_FAILURE;

        return ret;
    }

    uds_status.uds_sid34_service.flash_program_crc = uds_status.uds_sid36_service.total_crc;

    // 写入编程起始地址和文件大小和文件crc32结果
    if (user_flash_n_word_write(APP_UPDATA_CHECK_DATA_ADDR,
                                &uds_status.uds_sid34_service.flash_program_addr, 3) == 0) {

        ret = -NRC_GENERAL_PROGRAMMING_FAILURE;

        return ret;
    }

    // 准备数据
    routine_ctrl_pstv_resp->positive_resp_id = USD_GET_POSITIVE_RSP(routine_ctrl_req->sid);

    routine_ctrl_pstv_resp->subfunction = routine_ctrl_req->subfunction;

    routine_ctrl_pstv_resp->rid = routine_ctrl_req->rid;

    endian_shift((uint8_t *)(&routine_ctrl_pstv_resp->rid), 2);

    ret = ROUTINE_CTRL_POSTV_RESP_REQ_RESULT_MESSAGE_LEN;

    return ret;
}

routine_control_str user_sid31_table[] = {
    { START_ROUTINE, ERASE_MEM, 13, 6, uds_erase_start_routine },
    { START_ROUTINE, CHECK_MEM, 8, 6, uds_check_mem_start_routine },
    { REQ_ROUTINE_RESULT, ERASE_MEM, 4, 4, uds_req_erase_routine_result },
    { REQ_ROUTINE_RESULT, CHECK_MEM, 4, 4, uds_req_check_mem_routine_result },

};

int16_t Routine_Control_Port(uint8_t *rec_buf, uint8_t *rsp_buf, uint16_t rec_len)
{

    int16_t                  ret;
    routine_ctrl_req_struct *routine_ctrl_req;

    // 获取接收数据内容
    routine_ctrl_req = (routine_ctrl_req_struct *)rec_buf;

    // 获取有效子功能号
    routine_ctrl_req->subfunction = UDS_GET_SUB_FUNCTION(routine_ctrl_req->subfunction);

    // rid高低字节换序
    endian_shift((uint8_t *)&(routine_ctrl_req->rid), 2);

    USER_UDS_LOG("sub:%x,rid:%x\n", routine_ctrl_req->subfunction, routine_ctrl_req->rid);

    // 查询对应子功能服务
    for (uint8_t i = 0; i < (sizeof(user_sid31_table) / sizeof(user_sid31_table[0])); i++) {

        // USER_UDS_LOG("sub:%x,sub_func:%x\n", routine_ctrl_req->subfunction,
        // user_sid31_table[i].sub_func);

        if (routine_ctrl_req->subfunction == user_sid31_table[i].sub_func) {

            if (routine_ctrl_req->rid == user_sid31_table[i].rid) {

                // 请求长度检查
                if (rec_len != user_sid31_table[i].req_len) {

                    ret = -NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT;

                    return ret;
                }

                ret = user_sid31_table[i].handle_cb(rec_buf, rsp_buf);

                return ret;
            }
        }
    }

    // 没有找到对应的子功能服务
    // USER_UDS_LOG("[%s][%s][Line:%d][data:%x,%x]\n", __FILE__, __FUNCTION__, __LINE__,
    //              routine_ctrl_req->subfunction, routine_ctrl_req->rid);

    ret = -NRC_SUBFUNCTION_NOT_SUPPORTED;

    return ret;
}
